package com.ptkc.web;

import com.ptkc.constants.WebResult;
import com.ptkc.utils.NumberUtils;
import com.ptkc.utils.StringUtil;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author: Mr.Jiao
 * @date: 2019年01月21日
 */
@RestController
@RequestMapping(value = "/search/shopper")
public class ShopperController {

    private final String ORDER_INDEX = "runfast_order";

    private final String ORDER_TYPE = "order";

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    @GetMapping(value = "/distribution")
    public WebResult getShopperStatistics(HttpServletRequest request) throws IOException {
        String agentStr = request.getParameter("agents");
        String shopperStr = request.getParameter("shoppers");
        String starttime = request.getParameter("starttime");
        String endtime = request.getParameter("endtime");
        BoolQueryBuilder parentQueryBuilder = QueryBuilders.boolQuery();
        parentQueryBuilder.must(QueryBuilders.termsQuery("status", Arrays.asList(-1,8)));
        if(NumberUtils.isPositiveInteger(starttime) && NumberUtils.isPositiveInteger(endtime)){
            parentQueryBuilder.must(QueryBuilders.rangeQuery("createTime").from(starttime, true).to(endtime, true));
        }
        if(StringUtil.isNotEmpty(agentStr)){
            parentQueryBuilder.must(QueryBuilders.termsQuery("agentId", agentStr.split(",")));
        }
        if(StringUtil.isNotEmpty(shopperStr)){
            parentQueryBuilder.must(QueryBuilders.termsQuery("shopperId", shopperStr.split(",")));
        }
        parentQueryBuilder.mustNot(QueryBuilders.termQuery("isDeliver", 1));
        Map notParamMap = new HashMap();
        SumAggregationBuilder aggShopperCount = AggregationBuilders.sum("aggShopperCount").script(new Script(ScriptType.STORED, null, "runfast_order_of_shopper_count", notParamMap));
        SumAggregationBuilder aggShopperAmount = AggregationBuilders.sum("aggShopperAmount").script(new Script(ScriptType.STORED, null, "runfast_order_of_shopper_amount", notParamMap));
        SumAggregationBuilder aggCompletedOuttimeCount = AggregationBuilders.sum("aggCompletedOuttimeCount").script(new Script(ScriptType.STORED, null, "runfast_order_completed_outtime_count", notParamMap));
        SumAggregationBuilder aggOrderAllCanceledCount = AggregationBuilders.sum("aggOrderAllCanceledCount").script(new Script(ScriptType.STORED, null, "runfast_order_all_canceled_count", notParamMap));
        SumAggregationBuilder aggOrderNegativeCount = AggregationBuilders.sum("aggOrderNegativeCount").script(new Script(ScriptType.STORED, null, "runfast_order_negative_count", notParamMap));
        TermsAggregationBuilder termShopperId = AggregationBuilders.terms("termShopperId").field("shopperId");

        termShopperId.subAggregation(aggShopperCount).subAggregation(aggShopperAmount).subAggregation(aggCompletedOuttimeCount)
                .subAggregation(aggOrderAllCanceledCount).subAggregation(aggOrderNegativeCount);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.from(0).size(0).query(parentQueryBuilder).aggregation(termShopperId);
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(ORDER_INDEX).types(ORDER_TYPE).source(sourceBuilder);
        SearchResponse response = this.restHighLevelClient.search(searchRequest);
        if(response.status() != RestStatus.OK){
            return WebResult.fail("查询失败!");
        }
        List<Object> result = new ArrayList<>();
        Aggregations aggregations = response.getAggregations();
        if(aggregations != null){
            Terms termShopper = aggregations.get("termShopperId");
            if(termShopper != null){
                List<? extends Terms.Bucket> buckets = termShopper.getBuckets();
                if(buckets != null){
                    String[] aggKeys = new String[]{
                            "aggShopperCount",
                            "aggShopperAmount",
                            "aggCompletedOuttimeCount",
                            "aggOrderAllCanceledCount",
                            "aggOrderNegativeCount"
                    };
                    buckets.forEach(bucket -> {
                        if(bucket != null){
                            String shopperId = bucket.getKeyAsString();
                            if(NumberUtils.isPositiveInteger(shopperId)){
                                Aggregations itemAggregations = bucket.getAggregations();
                                if(itemAggregations != null){
                                    Map item = new HashMap();
                                    for(String key : aggKeys){
                                        Sum keySum = itemAggregations.get(key);
                                        Object value = null;
                                        if(key.endsWith("Count")){
                                            if(keySum == null){
                                                value = 0;
                                            }else{
                                                value = (int)keySum.getValue();
                                            }
                                        }else {
                                            if (keySum == null) {
                                                value = 0.0;
                                            } else {
                                                value = BigDecimal.valueOf(keySum.getValue()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                            }
                                        }
                                        String itemName = key.substring(3,4).toLowerCase() + key.substring(4,key.length());
                                        item.put(itemName, value);
                                    }
                                    item.put("shopperId", Integer.valueOf(shopperId));
                                    result.add(item);
                                }
                            }
                        }
                    });
                }
            }
        }
        return WebResult.ok(result);
    }

}
